#include "uprint.h"

#if (CONFIG_USING_DEBUG > 0)
#if (CONFIG_USING_DEBUG == 1)
static uint8_t xdata dbg_mem _at_ 0xFFFF;
#endif


#if (CONFIG_USING_DEBUG == 1)
void uputc(uint8_t uart_port, char ch)
{
    dbg_mem = ch;
    uart_port = uart_port;
}
#elif ((CONFIG_USING_DEBUG == 2) || (CONFIG_MODE == CONFIG_HARDWARE_TEST_LOG))
void uputc(uint8_t uart_port, char ch)
{
#if (CONFIG_IC_TYPE == CHIP_SS888X)
    uart0_putc(uart_port, ch);
#else
    uart_port = uart_port;
    uart0_putc(ch);
#endif
}
#else
#define uputc(uart_port, ch)                    (uart_port, ch)
#endif

/**
 * @brief Format serial data
 * eg. 
 * uprintf(SECOND_UART, "AN2* %d ", adc_get_an2());
 * @param uart_port 
 * @param format x: hex, d: decimal
 * @param number parameter
 */
void uprintf(uint8_t uart_port, const char *format, int16_t number)
{
    while (*format) {
        if (*format == '%') {
            if (*(format + 1) == 'x') {
                uprint_hex(uart_port, number);
                format += 2;
                continue;
            } else if (*(format + 1) == 'd') {
                if (number < 0) {
                    number = 0 - number;
                    uputc(uart_port, '-');
                }
                uprint_dec(uart_port, number);
                format += 2;
                continue;
            }
        } else if (*format == '\n') {
            uputc(uart_port, '\r');
        }

        uputc(uart_port, *format);
        format++;
    }
    sys_delay_ms(2);
}

/**
 * @brief The function is to convert input 0~65535(0x0000~0xFFFF) to decimal and print numbers one by one
 * eg. 65535(0xFFFF), break down into 6/5/5/35, and print it via serial port
 * 
 * @param num 
 */
void uprint_dec(uint8_t uart_port, uint16_t num)
{
    bool got_non_zero = false;

    uint8_t i;
    uint8_t tmp;
    uint16_t ex10_val;

    if (num == 0) {
        uputc(uart_port, '0');
        return;
    }

    i = 5;
    while (i) {
        i--;

        ex10_val = ex_10(i);

        tmp = num / ex10_val;
        num %= ex10_val;
        if (tmp == 0 && !got_non_zero)
            continue;

        got_non_zero = true;
        uputc(uart_port, tmp + '0');
    }
}
/**
 * @brief Convert uint_16(0x0000~0xFFFF) to hex (bytes) and print through serial port
 * eg. 0xFFFF, break down into F/F/F/F, and print it via serial port
 * @param uart_port 
 * @param num 
 */
void uprint_hex(uint8_t uart_port, uint16_t num)
{
    bool got_non_zero = false;

    uint8_t i;
    uint8_t tmp;

    if (num == 0) {
        uputc(uart_port, '0');
        return;
    }

    i = 16;
    while (i) {
        i -= 4;
        tmp = (num >> i) & 0xf;

        if (tmp == 0 && !got_non_zero)
            continue;

        got_non_zero = true;
        if (tmp >= 10)
            uputc(uart_port, tmp + 'a' - 10 );
        else
            uputc(uart_port, tmp + '0');
    }
}

/**
 * @brief The function is to Convert the argument to the nth power of 10 and return
 * 
 * @param num 
 * @return uint16_t = 10^num
 */
uint16_t ex_10(uint8_t num)
{
    uint8_t i;
    uint16_t tmp = 1;

    for (i = 0; i < num; i++)
        tmp = (tmp << 3) + (tmp << 1);  // * 10

    return tmp;     //tmp = 10^num
}
#endif
